home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 139_01.zip / KED.C < prev    next >
Text File  |  1993-06-03  |  34KB  |  944 lines

  1. /*
  2. TITLE:        Karel The Robot;
  3. VERSION:    1.0;
  4. DATE:        09/27/1984;
  5. DESCRIPTION:
  6.     "Part 1 of source code for syntax-directed 
  7.      editor KED.  Used for building programs to
  8.      be executed in KAREL's world.";
  9. KEYWORDS:    Syntax, editor;
  10. SYSTEM:        CP/M 2+;
  11. FILENAME:    KED.C;
  12. AUTHORS:    Linda Rising;
  13. COMPILERS:    BDS C;
  14. REFERENCES:
  15.     AUTHOR: Richard E. Pattis;
  16.     TITLE: "KAREL the Robot: A Gentle Introduction
  17.         to the Art of Programming";
  18.     CITATION: "";
  19. ENDREF
  20. */
  21.  
  22.  
  23. #include <bdscio.h>                    /* standard library header */
  24. #include <ked.h>                            /* globals for editor */
  25.  
  26.  
  27. main(argc,argv)
  28. int argc;                         /* number of arguments for main */           char **argv;                                        /* arg vector */
  29. {
  30.            int i;                             /* next instruction */
  31.            int stop;                        /* boolean to end pgm */
  32.            char nextcomm[MAXLINE];       /* buffer for next instr */
  33.            struct tnode *alloc();            /* allocate function */
  34.            
  35.            stop = 0;                        /* not end of session */ 
  36.            insert = 0;                         /* not insert mode */
  37.            first = last = 0;        /* no entries in symbol table */
  38.            tempend = NULL;                  /* last node inserted */
  39.            temp = NULL;                /* last instr in construct */
  40.  
  41.            if (argc < 3)               /* check for two filenames */
  42.                printf("MISSING FILENAME(S)\n");
  43.            else { 
  44.               initinstr();       /* initialize arrays of commands */
  45.               if (fopen(argv[1],ibuf1) == ERROR) {
  46.                   p = alloc(24);             /* create first node */
  47.                   pr = NULL;
  48.                   tree(6,0,5,1,1,0,1,0);
  49.                   endof = pr = curr = root = p;        
  50.                   p = root->sub = alloc(24); 
  51.                   printf("TYPE MN TO SEE MENU \n");
  52.                   print(root,CONSOLE);
  53.                   prompt("  ",3,"",12,0);
  54.                } else {                            /* if old file */
  55.                     createtree();           /* read in parse tree */
  56.                     curr = root;
  57.                     reply(20);   
  58.                  }
  59.                while (!stop) {
  60.                    i = readin(nextcomm);  /* get the next command */
  61.                    stop = reply(i,argv); /* make correct response */
  62.                }
  63.           }
  64.                   
  65. }
  66.  
  67.  
  68.  
  69. initinstr()    /* initialize arrays of commands */
  70. {
  71.           int i;
  72.           char *alloc();
  73.  
  74. /* allocate space for array entries */
  75. for (i = 0; i < MAXCOMM; i++)   
  76.      comm[i] = alloc(4);
  77. for (i = 0; i < MAXTEST; i++)
  78.      test[i] = alloc(2);
  79. for (i = 0; i < MAXNAME; i++)
  80.      iname[i] = alloc(10);  
  81.  
  82. /* initialize editor commands */
  83. comm[0] = "m";            comm[1] = "tl";
  84. comm[2] = "pi";           comm[3] = "pu";
  85. comm[4] = "to";           comm[5] = "b";
  86. comm[6] = "bepg";         comm[7] = "bx";
  87. comm[8] = "nd";           comm[9] = "ndx";
  88. comm[10] = "ndc";         comm[11] = "if";
  89. comm[12] = "th";          comm[13] = "el";
  90. comm[14] = "it";          comm[15] = "wh";
  91. comm[16] = "df";          comm[17] = "n";
  92. comm[18] = "n-";          comm[19] = "d";
  93. comm[20] = "p";           comm[21] = "i";
  94. comm[22] = "t";           comm[23] = "s";
  95. comm[24] = "q";           comm[25] = "mn";
  96. comm[26] = "n--";         comm[27] = "l";
  97. comm[28] = "nc";      comm[29] = "c";
  98.  
  99.  
  100. /* initialize booleans for Karel's programs */
  101. test[0] = "n";            test[1] = "nn";
  102. test[2] = "s";            test[3] = "ns";
  103. test[4] = "e";            test[5] = "ne";
  104. test[6] = "w";            test[7] = "nw";
  105. test[8] = "c";            test[9] = "nc";
  106. test[10] = "b";           test[11] = "nb";
  107. test[12] = "f";           test[13] = "nf";
  108. test[14] = "l";           test[15] = "nl";
  109. test[16] = "r";           test[17] = "nr";
  110. test[18] = "mn";
  111.  
  112. /* initialize commands for Karel's programs */
  113. iname[0] = "move";        iname[1] = "turnleft";
  114. iname[2] = "pickbeeper";  iname[3] = "putbeeper";
  115. iname[4] = "turnoff";     iname[5] = "begin";
  116. iname[6] = "end";         iname[7] = "if";
  117. iname[8] = "then";        iname[9] = "else";
  118. iname[10] = "iterate";    iname[11] = "while";
  119.  
  120. }
  121.  
  122.  
  123. reply(i,argv)         /* call proper function to handle input */
  124. int i;
  125. char **argv;
  126. {
  127.       int d,valid;
  128.           struct tnode *advance();    
  129.     
  130.           if (i < 0) {                  /* user-defined instr */
  131.               i = -i - 1;         /* converted to distinguish */
  132.               defindst(i);             /* from other commands */
  133.               return 0;
  134.           }
  135.           else {
  136.              switch(i) {
  137.              case 0:      /* move */
  138.              case 1:      /* turnleft */
  139.              case 2:      /* pickbeeper */
  140.              case 3:      /* putbeeper */
  141.              case 4:      /* turnoff */
  142.                 commandst(i);         
  143.                 return 0;
  144.              case 5:      /* BEGIN */
  145.                 compoundst(i);
  146.                 return 0;
  147.              case 7:      /* BEGINNING-OF-EXECUTION */
  148.                 if (insert)
  149.                     printf("COMMAND CAN'T BE INSERTED\n?"); 
  150.                 else execst(i);
  151.                 return 0;
  152.              case 8:      /* END */
  153.         if (pr->instr == THEN) 
  154.            endcons();
  155.         if (insert && insertnode->instr == ND &&
  156.             insertnode->del != NEWINSTR &&
  157.            (pr->indent - 1) == (insertnode->indent))
  158.            printf("END NOT REQUIRED\n?");
  159.         else {
  160.            valid = endst(i);
  161.            if (valid) {
  162.                       endcons();
  163.               prompt("",3,"",12,i);
  164.            }
  165.         }
  166.                 return 0;
  167.              case 9:      /* END-OF-EXECUTION */
  168.                 if (insert)
  169.                     printf("COMMAND CAN'T BE INSERTED\n?");
  170.                 else {
  171.                    if (pr->instr == THEN)  /* automatically end */
  172.                        endcons();                /* THEN and BX */
  173.                    if (pr->indent == 2)
  174.                        endcons();
  175.                    exendst(i);
  176.                 } 
  177.                 return 0;
  178.              case 10:      /* end construct */
  179.                 if (pr->comp == 3)   /* compound statement */
  180.                     printf("END REQUIRED\n");
  181.                 else endcons();
  182.                 prompt("",3,"",12,i);    
  183.                 return 0;
  184.              case 11:      /* IF */
  185.                 ifst(i);
  186.                 return 0;
  187.              case 13:      /* ELSE */
  188.                 elst(i);
  189.                 return 0;
  190.              case 14:      /* ITERATE */
  191.                 iterst(i);
  192.                 return 0;
  193.              case 15:      /* WHILE */
  194.                 whilst(i);
  195.                 return 0;
  196.              case 16:      /* DEFINE-NEW-INSTRUCTION */
  197.                 defst(i);
  198.                 return 0;
  199.              case 17:      /* advance pointer */
  200.                 endinsert();
  201.                 if (!insert) 
  202.                     if (curr == endof)
  203.                         printf("END OF FILE\n");
  204.                     else {
  205.                        curr = advance(curr);
  206.                        print(curr,CONSOLE);
  207.                     } 
  208.                 printf("?");
  209.                 return 0;
  210.              case 18:      /* reverse pointer */
  211.                 endinsert();
  212.                 if (!insert) {
  213.                     if (curr->prev != NULL)
  214.                         curr = curr->prev;
  215.                     print(curr,CONSOLE);
  216.                 }
  217.                 printf("?");
  218.                 return 0;
  219.              case 19:      /* delete */
  220.                 endinsert();
  221.                 if (!insert) 
  222.                     delete();
  223.                 printf("?");
  224.                 return 0;
  225.              case 20:      /* print 20 lines */
  226.                 endinsert();
  227.                 if (!insert) {
  228.                     print(curr,CONSOLE);
  229.                     for (i = 0; i < 20; i++) {
  230.                          if (curr == endof) {
  231.                              printf("END OF FILE\n");
  232.                              break;
  233.                         } else {
  234.                              curr = advance(curr);
  235.                              print(curr,CONSOLE);
  236.                           }
  237.                      }  
  238.                 }
  239.                 printf("?");
  240.                 return 0;
  241.              case 21:      /* insert */
  242.                 if (insert)
  243.                     printf("ALREADY IN INSERT MODE\n");
  244.                 else if (p != pr)       /* NDX not added */
  245.                          printf("INSERT ONLY AFTER END PGM\n");
  246.                      else if ((curr->indent > 2 && curr->instr !=ND) ||
  247.                   (curr->instr == BEG) ||
  248.                   (d = curr->del) == TEST || d == POSINT || 
  249.                   (d == NEWINSTR && curr->prev->instr == DEF))
  250.                               printf("CAN'T INSERT INSIDE CONSTRUCT\n");
  251.                           else insertinstr();  
  252.                 printf("?");
  253.                 return 0;
  254.              case 22:      /* go to top of pgm  */
  255.                 endinsert();
  256.                 if (!insert) {
  257.                     curr = root;  
  258.                     print(curr,CONSOLE);
  259.                 } 
  260.                 printf("?");
  261.                 return 0;
  262.              case 23:      /* save file */
  263.                 endinsert();
  264.                 if (!insert) {
  265.                     if (p != pr)   /* NDX not added */
  266.                         printf("PLEASE END PROGRAM \n");
  267.                     else savetree(root,argv);
  268.                 }
  269.                 printf("?");
  270.                 return 0;
  271.              case 24:      /* quit edit program */
  272.                 endinsert();
  273.                 if (!insert) {
  274.                     printf("HAS PROGRAM BEEN SAVED? (Y/N)\n");
  275.                     if ((i = toupper(getchar())) == 'Y') 
  276.                          return 1;
  277.                     else {
  278.                        printf("\n EXIT EDITOR ANYWAY? (Y/N)\n");
  279.                        if ((i = toupper(getchar())) == 'Y') 
  280.                           return 1;
  281.                     }
  282.         }
  283.         printf("\n?");
  284.         return 0;
  285.              case 25:      /* output menu */
  286.                 menu();
  287.                 printf("?");
  288.                 return 0;
  289.              case 26:      /* go back 10 lines */
  290.                 endinsert();
  291.                 if (!insert) {
  292.                     for (i = 0; i < 10; i++) 
  293.                          if (curr->prev != NULL)
  294.                              curr = curr->prev;
  295.                          print(curr,CONSOLE);
  296.                 }
  297.                 printf("?");
  298.                 return 0;
  299.              case 27:      /* list entire pgm */
  300.                 endinsert();
  301.                 if (!insert) {
  302.                     print(curr,CONSOLE);
  303.                     while (curr != endof) {
  304.                         curr = advance(curr);
  305.                         print(curr,CONSOLE);
  306.                     } 
  307.                     printf("END OF FILE\n");
  308.                 }
  309.                 printf("?");
  310.                 return 0;
  311.              case 28:      /* advance to next construct */
  312.                 endinsert();
  313.                 if (!insert) {
  314.            if (curr != endof)
  315.                       while ((curr = advance(curr))->cons != 1)
  316.                           if (curr == endof)
  317.                              break;
  318.                    print(curr,CONSOLE);
  319.                 }
  320.                 printf("?");
  321.                 return 0;
  322.          case 29:      /* print current line */
  323.         endinsert();
  324.         if (!insert)
  325.            print(curr,CONSOLE);
  326.         return 0; 
  327.             }
  328.         }
  329. }
  330.  
  331.  
  332. defindst(i)                 /* user-defined instruction entered */
  333. int i;
  334. {
  335.          int j,in,d,fn,fs,b,t,l,*valid;
  336.          struct tnode *allocp();
  337.  
  338.          in = checkin(&valid);             /* correct location? */
  339.          b = checkcomp(&valid);          /* compound statement? */
  340.          if (valid) {
  341.              j = 0;                            
  342.              while (new[i].loc[j] != NULL)      /* find loc for */
  343.                 if (++j == 15) {           /* next use of instr */
  344.                       printf("MAXIMUM NUMBER OF USES OF "); 
  345.            printf("DEFINITION EXCEEDED\n?");
  346.            return;
  347.             }
  348.              new[i].loc[j] = p;
  349.              new[i].loc[++j] = NULL;
  350.              d = 4;                      /* line may be deleted */
  351.              fn = 0;                   /* any instr may be next */
  352.              fs = 4;                      /* no component instr */
  353.              t = 0;            /* not start or end of construct */
  354.              l = pr->lastin;        /* last valid sym tab entry */    
  355.              tree(i,in,d,fn,fs,b,t,l);
  356.              p = p->next = allocp();
  357.              print(curr,CONSOLE);
  358.              prompt("",3,"",12,0); 
  359.           }
  360. }
  361.  
  362.  
  363. commandst(i)    /* move, turnleft, pickbeeper, putbeeper, turnoff */
  364. int i;
  365. {
  366.           int in,d,fn,fs,b,t,l,*valid;
  367.           struct tnode *allocp();
  368.  
  369.           in = checkin(&valid);              /* correct location? */
  370.           b = checkcomp(&valid);           /* compound statement? */
  371.           if (valid) {
  372.               d = 1;                       /* line may be deleted */
  373.               fn = 0;                    /* any instr may be next */
  374.               fs = 4;                       /* no component instr */    
  375.               t = 0;             /* not start or end of construct */
  376.               l = pr->lastin;         /* last valid sym tab entry */
  377.               tree(i,in,d,fn,fs,b,t,l);    
  378.               p = p->next = allocp();
  379.               print(curr,CONSOLE);
  380.               prompt("",3,"",12,0);
  381.           }
  382. }
  383.  
  384.  
  385. compoundst(i)                                    /* BEGIN entered */
  386. int i;
  387. {
  388.           int in,d,fn,fs,b,t,l;
  389.           struct tnode *allocp();
  390.  
  391.           switch (pr->comp) {
  392.           case 1:                          /* valid loc for begin */
  393.              in = pr->indent + 1;           /* for pretty printer */
  394.              d = 0;           /* entire construct must be deleted */
  395.              fn = 4;                   /* no valid next construct */
  396.              fs = 0;                      /* any instr may follow */ 
  397.              b = 3;                         /* compound statement */
  398.              t = 0;              /* not start or end of construct */
  399.              l = pr->lastin;          /* last valid sym tab entry */
  400.              tree(i,in,d,fn,fs,b,t,l);
  401.              p = p->sub = allocp();
  402.              print(curr,CONSOLE);
  403.              prompt("  ",3,"",12,0);        
  404.              break;
  405.          case 0:                       /* incorrect loc for BEGIN */
  406.          case 2:
  407.          case 3:                    
  408.             printf("BAD LOCATION FOR BEGIN. TYPE MN TO SEE MENU.\n?");
  409.          }
  410. }
  411.  
  412.  
  413. execst(i)                       /* BEGINNING-OF-EXECUTION entered */
  414. int i;
  415. {
  416.           int in,d,fn,fs,b,t,l;
  417.           struct tnode *allocp();
  418.  
  419.           if (pr->nfollow != 1) {
  420.              printf("BAD LOCATION FOR BEGINNING-OF-EXECUTION. ");
  421.          printf("TYPE MN TO SEE MENU.\n?");
  422.           }  else {
  423.                 in = 1;                     /* for pretty printer */
  424.                 d = 5;              /* construct can't be deleted */
  425.                 fn = 3;     /* no valid next construct except NDX */
  426.                 fs = 0;                   /* any instr may follow */
  427.                 b = 0;                /* not a compound statement */
  428.                 t = 1;                      /* start of construct */
  429.                 l = 15;               /* use any instr in sym tab */
  430.                 tree(i,in,d,fn,fs,b,t,l);
  431.                 p = p->sub = allocp();
  432.                 print(curr,CONSOLE);
  433.                 prompt("  ",3,"",12,0);
  434.              }
  435. }
  436.  
  437.  
  438. endst(i)                                           /* END entered */
  439. int i;
  440. {
  441.           int in,d,fn,fs,b,t,l,valid;
  442.           struct tnode *allocp();
  443.  
  444.           if (pr->comp != 3) {
  445.               printf("STRUCTURE NOT A COMPOUND STATEMENT\n?");
  446.           valid = 0;
  447.           } else {
  448.             valid = 1;
  449.                 in = pr->indent - 1;         /* for pretty printer */
  450.                 d = 0;         /* entire construct must be deleted */
  451.                 fn = fs = 4;                 /* no valid followers */
  452.                 b = 0;          /* not start of compound statement */
  453.                 t = 2;                         /* end of construct */
  454.                 l = pr->lastin;        /* last valid sym tab entry */
  455.                 tree(i,in,d,fn,fs,b,t,l);
  456.                 p = p->next = allocp();
  457.                 print(curr,CONSOLE);
  458.              }
  459.       return valid;
  460. }
  461.  
  462.  
  463. exendst(i)                             /* END-OF-EXECUTION entered */
  464. int i;
  465. {
  466.           int in,d,fn,fs,b,t,l;
  467.  
  468.           if (pr->nfollow != 3)
  469.              printf("BAD LOCATION FOR END PGM. TYPE MN TO SEE MENU.\n?");
  470.           else {
  471.              in = 1;                         /* for pretty printer */
  472.              d = 5;                  /* construct can't be deleted */
  473.              fn = fs = 4;                    /* no valid followers */
  474.              b = 0;             /* not start of compound statement */
  475.              t = 2;                            /* end of construct */
  476.              l = pr->lastin;           /* last valid sym tab entry */
  477.              tree(i,in,d,fn,fs,b,t,l);
  478.              pr = curr = p;
  479.              print(p,CONSOLE);
  480.              printf("?");
  481.           }
  482. }   
  483.  
  484.  
  485. ifst(i)                                              /* IF entered */
  486. int i;
  487. {
  488.           int j,in,d,fn,fs,b,t,l,*valid,c;
  489.           struct tnode *allocp();
  490.  
  491.           in = checkin(&valid);               /* correct location? */
  492.           b = checkcomp(&valid);            /* compound statement? */
  493.           if (valid) {
  494.               d = 0;           /* entire construct must be deleted */
  495.               fn = 0;           /* any instr may be next construct */
  496.               fs = 2;                      /* only test may follow */
  497.               t = 1;                         /* start of construct */
  498.               l = pr->lastin;          /* last valid sym tab entry */
  499.               tree(i,in,d,fn,fs,b,t,l);
  500.               p = p->sub = allocp();
  501.               do {
  502.            for (j = 0; j < in; j++)
  503.            printf("  ");
  504.            prompt("IF ",1," ",6,0);
  505.                c = testin();                           /* get test */
  506.                if (c == MENU) 
  507.                    menu();
  508.               } while (c == 18); 
  509.               print(pr->prev,CONSOLE);
  510.               print(pr,CONSOLE);
  511.               thenin();                                /* add THEN */
  512.               print(pr,CONSOLE); 
  513.               prompt("  ",3,"",12,0);
  514.           }
  515. }
  516.  
  517.  
  518. thenin()                                     /* store THEN in tree */
  519. {
  520.           int i,in,d,fn,fs,b,t,l;
  521.           struct tnode *allocp();
  522.  
  523.           i = THEN;
  524.           in = pr->prev->indent + 1;         /* for pretty printer */
  525.           d = 0;               /* entire construct must be deleted */
  526.           fn = 2;               /* only ELSE may be next construct */
  527.           fs = 0;                   /* any valid instr may follow  */
  528.           b = 1;                 /* may precede compound statement */
  529.           t = 1;                             /* start of construct */
  530.           l = pr->lastin;              /* last valid sym tab entry */
  531.           tree(i,in,d,fn,fs,b,t,l);
  532.           p = p->sub = allocp();
  533. }
  534.  
  535.  
  536. elst(i)                                            /* ELSE entered */
  537. int i;
  538. {
  539.          int in,d,fn,fs,b,t,l,*valid;
  540.          struct tnode *allocp();
  541.  
  542.          if (pr->nfollow != 2)
  543.              printf("ELSE NOT PAIRED WITH THEN\n?");
  544.          else {
  545.             i = ELS;
  546.             in = pr->indent;                 /* for pretty printer */
  547.             d = 0;             /* entire construct must be deleted */
  548.             fn = 4;                     /* no valid next construct */
  549.             fs = 0;                  /* any valid instr may follow */
  550.             b = 1;               /* may precede compound statement */
  551.             t = 1;                           /* start of construct */
  552.             l = pr->lastin;            /* last valid sym tab entry */
  553.             tree(i,in,d,fn,fs,b,t,l);
  554.             p = p->sub = allocp();
  555.             print(curr,CONSOLE);
  556.             prompt("  ",3,"",12,0);
  557.         }
  558. }
  559.  
  560.  
  561. iterst(i)                                       /* ITERATE entered */
  562. int i;
  563. {
  564.           int j,in,d,fn,fs,b,t,l,*valid;
  565.           struct tnode *allocp();
  566.  
  567.           in = checkin(&valid);               /* correct location? */
  568.           b = checkcomp(&valid);            /* compound statement? */
  569.           if (valid) {
  570.               d = 0;           /* entire construct must be deleted */
  571.               fn = 0;     /* any valid instr may be next construct */ 
  572.               fs = 2;                   /* only pos int may follow */
  573.               t = 1;                         /* start of construct */
  574.               l = pr->lastin;          /* last valid sym tab entry */
  575.               tree(i,in,d,fn,fs,b,t,l);
  576.               p = p->sub = allocp();
  577.           for (j = 0; j < in; j++)
  578.          printf("  "); 
  579.               prompt("ITERATE ",2," TIMES",22,0);
  580.               intin();                              /* get pos int */
  581.               printf("\n");
  582.               print(pr->prev,CONSOLE);
  583.               print(pr,CONSOLE);
  584.               prompt("  ",3,"",12,0);
  585.          }
  586. }
  587.  
  588.  
  589. whilst(i)                                         /* WHILE entered */
  590. int i;
  591. {
  592.           int j,in,d,fn,fs,b,t,l,*valid,c;
  593.           struct tnode *allocp();
  594.  
  595.           in = checkin(&valid);               /* correct location? */
  596.           b = checkcomp(&valid);            /* compound statement? */
  597.           if (valid) {
  598.               d = 0;           /* entire construct must be deleted */
  599.               fn = 0;     /* any valid instr may be next construct */
  600.               fs = 2;                      /* only test may follow */
  601.               t = 1;                         /* start of construct */
  602.               l = pr->lastin;          /* last valid sym tab entry */
  603.               tree(i,in,d,fn,fs,b,t,l);
  604.               p = p->sub = allocp();
  605.               do {
  606.            for (j = 0; j < in; j++)
  607.           printf("  ");
  608.                prompt ("WHILE ",1," DO",8,0);
  609.                c = testin();                           /* get test */
  610.                if (c == MENU) 
  611.                    menu();
  612.               } while (c == MENU);
  613.               print(pr->prev,CONSOLE);
  614.               print(pr,CONSOLE);  
  615.               prompt("  ",3,"",12,0);
  616.           }
  617. }    
  618.          
  619.                            
  620.                       
  621.                                                                                                  
  622. defst(i)                          /* DEFINE-NEW-INSTRUCTION entered */
  623. int i;
  624. {
  625.           int in,d,fn,fs,b,t,l;
  626.           struct tnode *allocp();
  627.  
  628.           if (pr->nfollow != 1)
  629.              printf("BAD LOCATION FOR DEFINITION. TYPE MN TO SEE MENU.\n?");
  630.           else if (last == 14)
  631.           printf("MAXIMUM NUMBER OF DEFINITIONS EXCEEDED.\n?");
  632.       else {
  633.              in = 1;                          /* for pretty printer */
  634.              d = 0;             /* entire construct must be deleted */
  635.              fn = 1;        /* only DEF or BX may be next construct */
  636.              fs = 2;                    /* only new name may follow */ 
  637.              b = 0;             /* won't precede compound statement */
  638.              t = 1;                           /* start of construct */
  639.              if (pr->instr == DEF) 
  640.                  l = new[pr->lastin].nextin;
  641.              else l = pr->lastin;       /* last valid sym tab entry */
  642.              tree(i,in,d,fn,fs,b,t,l);
  643.              p = p->sub = allocp(); 
  644.              newin();                               /* get new name */
  645.              print(pr->prev,CONSOLE);
  646.              print(pr,CONSOLE);
  647.              compoundst(5);                            /* add BEGIN */
  648.           }
  649. }
  650.  
  651.  
  652. testin()                                      /* store test in tree */
  653. {
  654.           int i,in,d,fn,fs,b,t,l;
  655.           struct tnode *allocp();
  656.  
  657.           i = getest();
  658.           if (i != MENU) {
  659.               in = pr->indent;                /* for pretty printer */
  660.               d = 2;               /* no deletion, replacement only */
  661.               fn = 4;                          /* no next construct */
  662.               fs = 0;                       /* any instr may follow */
  663.               b = 1;              /* may precede compound statement */
  664.               t = 0;               /* not start or end of construct */
  665.               l = pr->lastin;           /* last valid sym tab entry */
  666.               tree(i,in,d,fn,fs,b,t,l);
  667.               p = p->sub = allocp();
  668.           }
  669.           return i;
  670. }
  671.  
  672.  
  673. getest()            /* get valid test */
  674. {
  675.           char w[MAXLINE];
  676.           int m;
  677.  
  678.           do {
  679.             inputs(w);   
  680.             if ((m = match(w,test,MAXTEST)) == NOMATCH)
  681.                printf("INVALID TEST. TYPE MN TO SEE MENU.\n?");
  682.           } while (m == NOMATCH);
  683.           return m;
  684. }
  685.  
  686.  
  687. intin()                              /* store positive number in tree */
  688. {
  689.           int i,in,d,fn,fs,b,t,l;
  690.           struct tnode *allocp();
  691.  
  692.           i = getint();
  693.           in = pr->indent;                      /* for pretty printer */
  694.           d = 3;                  /* may not be deleted, replace only */
  695.           fn = 4;                          /* no valid next construct */
  696.           fs = 0;                             /* any instr may follow */
  697.           b = 1;                    /* may precede compound statement */
  698.           t = 0;                     /* not start or end of construct */
  699.           l = pr->lastin;                 /* last valid sym tab entry */
  700.           tree(i,in,d,fn,fs,b,t,l);
  701.           p = p->sub = allocp();
  702. }
  703.  
  704.  
  705. getint()                                       /* get positive number */
  706.           char s[3];
  707.           int i,num;
  708.    
  709.           for (i = 0; (s[i] = getchar()) != ' '
  710.                  && s[i] != '\n'; ++i);
  711.           s[i] = '\0';                              /* read in string */
  712.           num = atoi(s);                    /* and convert to integer */
  713.           return num;
  714. }
  715.  
  716.  
  717. newin()                                     /* store new name in tree */
  718. {
  719.           int i,in,d,fn,fs,b,t,l;
  720.           struct tnode *allocp();
  721.  
  722.           i = last;                  /* next location in symbol table */
  723.       prompt("  DEFINE-NEW-INSTRUCTION ",4," AS",12,0);
  724.           getnew(i);
  725.           putintable(i);
  726.           in = pr->indent;                      /* for pretty printer */
  727.           d = 4;                  /* may not be deleted, replace only */
  728.           fn = 4;                          /* no valid next construct */
  729.           fs = 0;                     /* any defined instr may follow */
  730.           b = 1;                    /* may precede compound statement */
  731.           t = 0;                     /* not start or end of construct */
  732.           l = last;                       /* last valid sym tab entry */
  733.           tree(i,in,d,fn,fs,b,t,l);
  734.           p = p->sub = allocp();
  735. }
  736.  
  737.  
  738. getnew(i)                /* get unique new name */
  739. int i;
  740. {
  741.           int c,j,m;
  742.  
  743.           do {
  744.             if (inputs(new[i].defname) != ERROR &&
  745.             new[i].defname[0] >= 'a' &&
  746.         new[i].defname[0] <= 'z') {
  747.               m = match(new[i].defname,comm,MAXCOMM);
  748.               if (m == NOMATCH)
  749.                 for (j = 0; j < MAXNAME; j++)
  750.                   if ((c = strcomp(new[i].defname,iname[j])) == 0)
  751.                     m = 1;     
  752.               if (m == NOMATCH && last != first) 
  753.                 for (j = first; j != i; j = new[j].nextin)
  754.                   if ((c = strcomp(new[i].defname,new[j].defname)) == 0)
  755.                     m = 1;
  756.               if (m != NOMATCH)
  757.                 printf("\nNEW NAME MUST BE UNIQUE\n?");
  758.         } else {
  759.          printf("\nINVALID CHARACTERS IN NEW NAME\n?");
  760.          m = 1;
  761.           }                
  762.           } while (m != NOMATCH);
  763.           new[i].loc[0] = NULL;
  764. }
  765.  
  766.  
  767.  
  768. print(ptr,buf)                     /* pretty printer */
  769. struct tnode *ptr;
  770. FILE *buf;
  771. {
  772.           int d,i;
  773.  
  774.           d = ptr->del;
  775.           if (d == TEST || d == POSINT || d == NEWINSTR)
  776.               switch(ptr->prev->instr) {
  777.               case 11:             /* instr is an if test */
  778.                  printest(ptr,buf);
  779.                  fprintf(buf,"\n");
  780.                  return;
  781.               case 14:             /* instr is a pos num */
  782.                  fprintf(buf,"%2d TIMES\n", ptr->instr);
  783.                  return;
  784.               case 15:             /* instr is a while test */
  785.                  printest(ptr,buf);
  786.                  fprintf(buf," DO\n");
  787.                  return;
  788.               case 16:             /* instr is a new name */
  789.                  fprintf(buf,"%s AS\n",new[ptr->instr].defname);
  790.                  return;
  791.               }    
  792.           
  793.           for (i = 0; i < ptr->indent; i++)
  794.                fprintf(buf,"  ");  /* indent line */
  795.  
  796.           if (d == NEWINSTR) {
  797.              fprintf(buf,"%s",new[ptr->instr].defname);
  798.              endline(ptr,buf);
  799.              return;
  800.           }
  801.          
  802.           switch(ptr->instr) {
  803.           case 0:
  804.              fprintf(buf,"move");
  805.              endline(ptr,buf);
  806.              break;
  807.           case 1:
  808.              fprintf(buf,"turnleft");
  809.              endline(ptr,buf);
  810.              break;
  811.           case 2:
  812.              fprintf(buf,"pickbeeper");
  813.              endline(ptr,buf);
  814.              break;
  815.           case 3:
  816.              fprintf(buf,"putbeeper");
  817.              endline(ptr,buf);
  818.              break;
  819.           case 4:
  820.              fprintf(buf,"turnoff");
  821.              endline(ptr,buf);
  822.              break;
  823.           case 8:
  824.              fprintf(buf,"END");
  825.              endline(ptr,buf);
  826.              break;
  827.           case 5:
  828.              fprintf(buf,"BEGIN\n"); 
  829.              break;
  830.           case 6:
  831.              fprintf(buf,"BEGINNING-OF-PROGRAM\n");
  832.              break;
  833.           case 7:
  834.              fprintf(buf,"\n  BEGINNING-OF-EXECUTION\n");
  835.              break;
  836.           case 9:
  837.              fprintf(buf,"END-OF-EXECUTION\n");
  838.              fprintf(buf,"END-OF-PROGRAM\n");
  839.              break;
  840.           case 11:
  841.              fprintf(buf,"IF ");
  842.              break;
  843.           case 12:
  844.              fprintf(buf,"THEN\n");
  845.              break;
  846.           case 13:
  847.              fprintf(buf,"ELSE\n");
  848.              break;
  849.           case 14:
  850.              fprintf(buf,"ITERATE ");
  851.              break;
  852.           case 15:
  853.              fprintf(buf,"WHILE ");
  854.              break;
  855.           case 16:
  856.              fprintf(buf,"\n  DEFINE-NEW-INSTRUCTION ");
  857.              break;
  858.           }
  859. }
  860.  
  861.  
  862.  
  863. endline(ptr,buf)             /* add ; if required and start newline */
  864. struct tnode *ptr;
  865. FILE *buf;
  866. {
  867.           int i;
  868.          
  869.           i = ptr->next->instr;
  870.           if ((i == ND || i == NDX || i == ELS) &&
  871.             ptr->next->del != NEWINSTR)
  872.              fprintf(buf,"\n");
  873.           else fprintf(buf,";\n");  
  874. }
  875.  
  876.  
  877. printest(ptr,buf)     /* print test after IF or WHILE */
  878. struct tnode *ptr;
  879. FILE *buf; 
  880. {
  881.  
  882.           switch(ptr->instr) {
  883.           case 0:
  884.              fprintf(buf,"facing-north");
  885.              break;
  886.           case 1:
  887.              fprintf(buf,"not-facing-north");
  888.              break;
  889.           case 2:
  890.              fprintf(buf,"facing-south");
  891.              break;
  892.           case 3:
  893.              fprintf(buf,"not-facing-south");
  894.              break;
  895.           case 4:
  896.              fprintf(buf,"facing-east");
  897.              break;
  898.           case 5:
  899.              fprintf(buf,"not-facing-east");
  900.              break;
  901.           case 6:
  902.              fprintf(buf,"facing-west");
  903.              break; 
  904.           case 7:
  905.              fprintf(buf,"not-facing-west");
  906.              break;        
  907.           case 8:
  908.              fprintf(buf,"next-to-a-beeper");
  909.              break;
  910.           case 9:
  911.              fprintf(buf,"not-next-to-a-beeper");
  912.              break;
  913.           case 10:
  914.              fprintf(buf,"any-beepers-in-beeper-bag");
  915.              break;
  916.           case 11:
  917.              fprintf(buf,"no-beepers-in-beeper-bag");
  918.              break;
  919.           case 12:
  920.              fprintf(buf,"front-is-clear");
  921.              break;
  922.           case 13:
  923.              fprintf(buf,"front-is-blocked");
  924.              break;
  925.           case 14:
  926.              fprintf(buf,"left-is-clear");
  927.              break;
  928.           case 15:
  929.              fprintf(buf,"left-is-blocked");
  930.              break;
  931.           case 16:
  932.              fprintf(buf,"right-is-clear");
  933.              break;
  934.           case 17:
  935.              fprintf(buf,"right-is-blocked");
  936.              break;
  937.           case 18:
  938.              menu();
  939.              break;
  940.           }
  941. }
  942.  
  943.